//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V0.1.0
#include "w5500_driver.h"
#include <string.h>

static WHT_W5500_State_t WHT_W5500_State = { W5500_TRx_Idle , W5500_No_Error};


/**********************驱动初始化配置*********************/
static SemaphoreHandle_t TRx_xSemaphore;//二值信号量句柄
static WHT_SPI_Cache_t wht_cache;
static volatile unsigned int* W5500_Soft_NSS;
static volatile unsigned int* W5500_Reset;
static volatile unsigned int* W5500_Int;

static void WHT_TRx_Idle_IT_Callback(void);
static void WHT_W5500_Driver_GPIO_Init(void)
{
	if (WHT_SPI_BUS2->Config.NSS == Soft_NSS)//配置片选引脚
	{
		WHT_GPIO_BSP.WHT_Set_Clock(W5500_NSS_GPIO_PORT, ENABLE);
		WHT_GPIO_BSP.WHT_Set_Pin(W5500_NSS_GPIO_PORT, W5500_NSS_GPIO_PIN, Hig);
		WHT_GPIO_BSP.WHT_Set_Mode(W5500_NSS_GPIO_PORT, W5500_NSS_GPIO_PIN, Mode_Out_PP);
		WHT_GPIO_BSP.WHT_Register_Bit_Output(W5500_NSS_GPIO_PORT, W5500_NSS_GPIO_PIN, &W5500_Soft_NSS);
	}

	WHT_GPIO_BSP.WHT_Set_Clock(W5500_RESET_GPIO_PORT, ENABLE);
	WHT_GPIO_BSP.WHT_Set_Pin(W5500_RESET_GPIO_PORT, W5500_RESET_GPIO_PIN, Hig);
	WHT_GPIO_BSP.WHT_Set_Mode(W5500_RESET_GPIO_PORT, W5500_RESET_GPIO_PIN, Mode_Out_PP);
	WHT_GPIO_BSP.WHT_Register_Bit_Output(W5500_RESET_GPIO_PORT, W5500_RESET_GPIO_PIN, &W5500_Reset);

	WHT_GPIO_BSP.WHT_Set_Clock(W5500_INT_GPIO_PORT, ENABLE);
	WHT_GPIO_BSP.WHT_Set_Pin(W5500_INT_GPIO_PORT, W5500_INT_GPIO_PIN, Hig);
	WHT_GPIO_BSP.WHT_Set_Mode(W5500_INT_GPIO_PORT, W5500_INT_GPIO_PIN, Mode_IPU);
	WHT_GPIO_BSP.WHT_Register_Bit_Input(W5500_INT_GPIO_PORT, W5500_INT_GPIO_PIN, &W5500_Int);
}
static void WHT_Set_NSS_State_Callback(WHT_SPI_IO_State_enum state)
{
	*W5500_Soft_NSS = state;
}
static void WHT_W5500_Driver_Init(void)
{
    if (WHT_SPI_BUS2_Init() != 0)
    {
        /* 总线初始化失败 */
        return;
    }
	WHT_W5500_Driver_GPIO_Init();
	wht_cache.Set_NSS_State_CB = WHT_Set_NSS_State_Callback;
	wht_cache.TRx_Finish_IT_CB = WHT_TRx_Idle_IT_Callback;

    TRx_xSemaphore = xSemaphoreCreateBinary();
}
/**********************驱动初始化配置*********************/

/************************** start read & write ********************************/
/*空闲中断回调函数*/
static void WHT_TRx_Idle_IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    xSemaphoreGiveFromISR(TRx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
static void WHT_W5500_Driver_Write_Data(uint8_t* const input_buf, uint32_t count)
{
	while (WHT_SPI_BUS2->Mutex == SPI_Lock)//等待互斥锁成功打开
		vTaskDelay(1);
	wht_cache.Dir = SPI_WO;
	wht_cache.Buffer_Count = count;
	wht_cache.Tx_Buffer = input_buf;
	wht_cache.Rx_Buffer = NULL;

	extern uint32_t SystemCoreClock;//out system_stm32f10x.c
	TickType_t Tick_Count = 0;
	switch (WHT_SPI_BUS2->Config.Clock_Div)
	{
	case APBx_DIV2:  Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide *   2 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV4:  Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide *   4 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV8:  Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide *   8 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV16: Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide *  16 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV32: Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide *  32 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV64: Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide *  64 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV128:Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide * 128 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV256:Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide * 256 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	}
	if (Tick_Count)
		WHT_SPI_BUS_OPS.Read_Write_DMA(WHT_SPI_BUS2, &wht_cache);
	else
		WHT_SPI_BUS_OPS.Read_Write_IT(WHT_SPI_BUS2, &wht_cache);
	
    if (WHT_SPI_BUS2->Mutex == SPI_Unlock)//传输结束
    {
		if (WHT_SPI_BUS2->State != SPI_No_Error)
			WHT_W5500_State.Error_State = W5500_Error;
    }
    else
        xSemaphoreTake(TRx_xSemaphore, portMAX_DELAY);//等待信号量
}
static void WHT_W5500_Driver_Read_Data(uint8_t* const input_buf,uint8_t* const output_buf, uint32_t count)
{
	while (WHT_SPI_BUS2->Mutex == SPI_Lock)//等待互斥锁成功打开
		vTaskDelay(1);
	wht_cache.Dir = SPI_RW;
	wht_cache.Buffer_Count = count;
	wht_cache.Tx_Buffer = input_buf;
	wht_cache.Rx_Buffer = output_buf;

	extern uint32_t SystemCoreClock;//out system_stm32f10x.c
	TickType_t Tick_Count = 0;
	switch (WHT_SPI_BUS2->Config.Clock_Div)
	{
	case APBx_DIV2:  Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide  *   2 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV4:  Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide  *   4 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV8:  Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide  *   8 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV16: Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide  *  16 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV32: Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide  *  32 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV64: Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide  *  64 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV128:Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide  * 128 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	case APBx_DIV256:Tick_Count = count * WHT_SPI_BUS2->Config.Bit_Wide  * 256 / (SystemCoreClock / 1000) / portTICK_RATE_MS; break;//单位ms/Tick;
	}
	if (Tick_Count)
		WHT_SPI_BUS_OPS.Read_Write_DMA(WHT_SPI_BUS2, &wht_cache);
	else
		WHT_SPI_BUS_OPS.Read_Write_IT(WHT_SPI_BUS2, &wht_cache);

    if (WHT_SPI_BUS2->Mutex == SPI_Unlock)//传输结束
    {
		if (WHT_SPI_BUS2->State != SPI_No_Error)
			WHT_W5500_State.Error_State = W5500_Error;
    }
    else
        xSemaphoreTake(TRx_xSemaphore, portMAX_DELAY);//等待信号量
}
/************************** end read & write **********************************/

static void WHT_W5500_Reset(void)
{
    *W5500_Reset = Low;
    WHT_Delay_us(2);
    *W5500_Reset = Hig;
    vTaskDelay(1600/portTICK_RATE_MS);
}

WHT_W5500_Driver_t WHT_W5500_Driver =
{
	.WHT_State      = &WHT_W5500_State,
	.WHT_Init       = WHT_W5500_Driver_Init,
	.WHT_Reset      = WHT_W5500_Reset,
	.WHT_Get_Int_State=NULL,
	.WHT_Read_Data  = WHT_W5500_Driver_Read_Data,
	.WHT_Write_Data = WHT_W5500_Driver_Write_Data,
};
